package com.goods.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.goods.business.entities.*;
import com.goods.business.mapper.*;
import com.goods.business.service.InStockService;
import com.goods.common.error.BusinessException;
import com.goods.common.vo.business.InStockItemVO;
import com.goods.common.vo.business.InStockVO;
import com.goods.common.vo.business.SupplierVO;
import com.goods.common.vo.system.PageVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Decheng Kong
 * @date 2021/11/9 08:56
 */
@Service
public class InStockServiceImpl implements InStockService {

    @Autowired
    private InStockMapper inStockMapper;
    @Autowired
    private SupplierMapper supplierMapper;

    @Autowired
    private InStockInfoMapper inStockInfoMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductStockMapper productStockMapper;

    @Override
    public PageVO<InStockVO> findInStockList(Integer pageNum, Integer pageSize, InStockVO inStockVO) {
        PageHelper.startPage(pageNum, pageSize);

        Example example = new Example(InStock.class);
        Example.Criteria criteria = example.createCriteria();

        if (inStockVO.getStatus() != null) {
            criteria.andEqualTo("status", inStockVO.getStatus());
        }

        if (inStockVO.getType() != null) {
            criteria.andEqualTo("type", inStockVO.getType());
        }

        if (inStockVO.getInNum() != null) {
            criteria.andEqualTo("inNum", inStockVO.getInNum());
        }

        if (inStockVO.getStartTime() != null && inStockVO.getEndTime() != null) {
            criteria.andBetween("createTime", inStockVO.getStartTime(), inStockVO.getEndTime());
        }


        List<InStock> inStocks = inStockMapper.selectByExample(example);
        List<InStockVO> collect = inStocks.stream().map(inStock -> {
            InStockVO inStockVO1 = new InStockVO();
            BeanUtils.copyProperties(inStock, inStockVO1);
            Supplier supplier = supplierMapper.selectByPrimaryKey(inStock.getSupplierId());
            BeanUtils.copyProperties(supplier, inStockVO1, "id", "createTime", "modifiedTime");
            inStockVO1.setSupplierName(inStockVO1.getName());
            return inStockVO1;

        }).collect(Collectors.toList());

        PageInfo<InStock> info = new PageInfo<>(inStocks);
        return new PageVO<>(info.getTotal(), collect);

    }

    @Override
    public Map<String, Object> findInStockDetailList(Integer pageNum, Integer pageSize, Integer id) {


        InStock inStock = inStockMapper.selectByPrimaryKey(id);

        // 查询供应商信息
        Long supplierId = inStock.getSupplierId();
        Supplier supplier = supplierMapper.selectByPrimaryKey(supplierId);
        SupplierVO supplierVO = new SupplierVO();
        BeanUtils.copyProperties(supplier, supplierVO);

        // 查询商品信息
        String inNum = inStock.getInNum();

        PageHelper.startPage(pageNum, pageSize);
        Example example = new Example(InStockInfo.class);
        example.createCriteria().andEqualTo("inNum", inNum);
        List<InStockInfo> inStockInfos = inStockInfoMapper.selectByExample(example);
        List<InStockItemVO> collect = inStockInfos.stream().map(inStockInfo -> {
            // 查询商品
            Example example1 = new Example(Product.class);
            example1.createCriteria().andEqualTo("pNum", inStockInfo.getpNum());
            Product product = productMapper.selectOneByExample(example1);
            // 转VO
            InStockItemVO inStockItemVO = new InStockItemVO();
            BeanUtils.copyProperties(product, inStockItemVO);
            // 设置数量
            inStockItemVO.setCount(inStockInfo.getProductNumber());
            return inStockItemVO;

        }).collect(Collectors.toList());
        // 商品的分页信息
        PageInfo<InStockInfo> info = new PageInfo<>(inStockInfos);
        Map<String, Object> res = new HashMap<>();
        res.put("total", info.getTotal());
        res.put("itemVOS", collect);
        res.put("supplierVO", supplierVO);
        res.put("status", inStock.getStatus());
        return res;

    }

    @Override
    public void updateInStockStatus(Long id, int code) {
        InStock inStock = inStockMapper.selectByPrimaryKey(id);
        inStock.setStatus(code);
        inStock.setModified(new Date());
        inStockMapper.updateByPrimaryKey(inStock);
    }

    @Transactional
    @Override
    public void deleteInStockById(Long id) {
        // 删除入库单明细
        InStock inStock = inStockMapper.selectByPrimaryKey(id);
        String inNum = inStock.getInNum();
        Example example = new Example(InStockInfo.class);
        example.createCriteria().andEqualTo("inNum", inNum);
        inStockInfoMapper.deleteByExample(example);

        // 删除入库单
        inStockMapper.deleteByPrimaryKey(id);

    }

    // @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Transactional
    @Override
    public void addIntoStock(InStockVO inStockVO) throws BusinessException {
        // 创建时间
        Date createDate = new Date();
        // 入库清单
        List<Object> products = inStockVO.getProducts();

        if (inStockVO.getSupplierId() == null) {
            // 新增来源
            long supplierId = insertSupplier(inStockVO, createDate);
            inStockVO.setSupplierId(supplierId);
        }

        // 已知来源
        // 新增入库单
        String inNum = insertInStock(inStockVO, createDate, products, inStockVO.getSupplierId());
        // TODO 事务不生效
        // test transition
        // if (inNum != null) {
        //     throw new BusinessException(BusinessCodeEnum.PRODUCT_IN_STOCK_NUMBER_ERROR);
        // }
        // 新增入库清单
        insertInStockInfo(createDate, products, inNum);
    }

    @Override
    public void auditInStock(Long id, int code) {
        InStock inStock = inStockMapper.selectByPrimaryKey(id);
        String inNum = inStock.getInNum();
        Example example = new Example(InStockInfo.class);
        example.createCriteria().andEqualTo("inNum", inNum);
        List<InStockInfo> inStockInfos = inStockInfoMapper.selectByExample(example);


        inStockInfos.forEach(inStockInfo -> {
            Example example1 = new Example(ProductStock.class);
            example1.createCriteria().andEqualTo("pNum", inStockInfo.getpNum());
            ProductStock productStock = productStockMapper.selectOneByExample(example1);

            if (productStock == null) {
                // 首次入库,执行物资入库初始化
                productStock = new ProductStock();
                productStock.setPNum(inStockInfo.getpNum());
                productStock.setStock(0L);
                productStockMapper.insertSelective(productStock);
            }
            // 更新物资库存数量
            productStock.setStock(productStock.getStock() + inStockInfo.getProductNumber());
            productStockMapper.updateByPrimaryKey(productStock);
        });
        // 更新状态
        updateInStockStatus(id, code);
    }


    private void insertInStockInfo(Date createDate, List<Object> products, String inNum) {
        products.forEach(object -> {

            String s = JSON.toJSONString(object);
            JSONObject jsonObject = JSONObject.parseObject(s);

            Product product = productMapper.selectByPrimaryKey(jsonObject.get("productId"));
            InStockInfo inStockInfo = new InStockInfo();
            inStockInfo.setInNum(inNum);
            inStockInfo.setpNum(product.getPNum());
            inStockInfo.setProductNumber((Integer) jsonObject.get("productNumber"));
            inStockInfo.setCreateTime(createDate);
            inStockInfo.setModifiedTime(createDate);
            inStockInfoMapper.insert(inStockInfo);
        });
    }


    private String insertInStock(InStockVO inStockVO, Date createDate, List<Object> products, long supplierId) {
        InStock inStock = new InStock();
        BeanUtils.copyProperties(inStockVO, inStock);
        inStock.setInNum(UUID.randomUUID().toString().replace("-", ""));
        inStock.setOperator("admin");
        inStock.setCreateTime(createDate);
        inStock.setModified(createDate);
        inStock.setProductNumber(products.size());
        inStock.setSupplierId(supplierId);
        inStock.setStatus(2);
        inStockMapper.insert(inStock);

        return inStock.getInNum();
    }


    private long insertSupplier(InStockVO inStockVO, Date createDate) {
        Supplier supplier = new Supplier();
        BeanUtils.copyProperties(inStockVO, supplier);
        supplier.setCreateTime(createDate);
        supplier.setModifiedTime(createDate);

        supplierMapper.insertSelective(supplier);
        // 主键回显
        return supplier.getId();
    }
}
